package com.example.netty;

import com.alibaba.fastjson.JSON;
import com.example.enums.MsgActionEnum;
import com.example.netty.entity.BinaryWebSocketFrameFile;
import com.example.netty.entity.ChatMessage;
import com.example.netty.entity.DataContent;
import com.example.utils.Base64Util;
import com.example.utils.JsonUtils;
import com.example.utils.MySendFile;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.util.concurrent.GlobalEventExecutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * 
 * @Description: 处理消息的handler
 * TextWebSocketFrame： 在netty中，是用于为websocket专门处理文本的对象，frame是消息的载体
 */
public class TextWebSocketHandler extends SimpleChannelInboundHandler<Object> {
	private static final Logger log = LoggerFactory.getLogger(TextWebSocketHandler.class);

	/**
	 * 	 用于记录和管理所有客户端的channle
	 */
	public static ChannelGroup users =
			new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
	


	@Override
	protected void channelRead0(ChannelHandlerContext ctx, Object msg) {


		if (msg instanceof BinaryWebSocketFrameFile) {
			System.out.println(11111);
		}
		if (msg instanceof MySendFile) {
			MySendFile sendFile = (MySendFile) msg;
			byte[] bytes = sendFile.getBytes();
			System.out.println(333333333);
		}
		if (msg instanceof TextWebSocketFrame) {
			TextWebSocketFrame tw=(TextWebSocketFrame)msg;
			String content = tw.text();


			DataContent dataContent = JSON.parseObject(content,DataContent.class);
		//	DataContent dataContent = JsonUtils.jsonToPojo(content, DataContent.class);

			Integer action = dataContent.getAction();
			System.out.println(dataContent);

			// 获取客户端传输过来的消息
			Channel currentChannel = ctx.channel();
			System.out.println(content);
			System.out.println(currentChannel);
			// 1. 获取客户端发来的消息

			// 2. 判断消息类型，根据不同的类型来处理不同的业务

				if (action.toString().equals("8")) {
					ChatMessage chatMessage = dataContent.getChatMsg();
					String msgText = chatMessage.getMsg();
					String receiverId = chatMessage.getReceiverId();
					Channel receiverChannel = UserChannelRel.get(receiverId);
					byte[] b=Base64Util.generateImage(dataContent.getExtand());
					// 	2.1  当websocket 第一次open的时候，初始化channel，把用的channel和userid关联起来


					log.info("服务器接收到二进制消息,消息长度:[{}]", tw.content().capacity());
					log.info("服务器接收到二进制消息,消息长度:[{}]", tw.content());
					ByteBuf byteBuf = Unpooled.directBuffer(b.length);
					byteBuf.writeBytes(b);
					//ctx.writeAndFlush(new BinaryWebSocketFrame(byteBuf));

					receiverChannel.writeAndFlush(
							new TextWebSocketFrame(
									content));
				} else	if (action.equals(MsgActionEnum.CONNECT.type)) {
				// 	2.1  当websocket 第一次open的时候，初始化channel，把用的channel和userid关联起来
				String senderId = dataContent.getChatMsg().getSenderId();
				UserChannelRel.put(senderId, currentChannel);

				// 测试
				for (Channel c : users) {
					System.out.println(c.id().asLongText());
				}
				UserChannelRel.output();
			} else if (action.equals(MsgActionEnum.CHAT.type)) {
				//  2.2  聊天类型的消息，把聊天记录保存到数据库，同时标记消息的签收状态[未签收]
				ChatMessage chatMessage = dataContent.getChatMsg();
				String msgText = chatMessage.getMsg();
				String receiverId = chatMessage.getReceiverId();
				String senderId = chatMessage.getSenderId();



				// 发送消息
				// 从全局用户Channel关系中获取接受方的channel
				Channel receiverChannel = UserChannelRel.get(receiverId);
				System.out.println("在线用户数::## ： "+UserChannelRel.getUserChannelRel().size()+" 个");
				if (receiverChannel == null) {
					// TODO channel为空代表用户离线，推送消息（JPush，个推，小米推送）
					System.out.println(receiverId +"::receiverChannel为空代表用户离线,用户离线");
				} else {
					// 当receiverChannel不为空的时候，从ChannelGroup去查找对应的channel是否存在
					Channel findChannel = users.find(receiverChannel.id());
					if (findChannel != null) {
						// 用户在线
						receiverChannel.writeAndFlush(
								new TextWebSocketFrame(
										content));
					} else {
						// 用户离线 TODO 推送消息
						System.out.println(receiverChannel.id()+"::2用户离线");
					}

				}

			} else if (action.equals(MsgActionEnum.SIGNED.type)) {
				//  2.3  签收消息类型，针对具体的消息进行签收，修改数据库中对应消息的签收状态[已签收]


			} else if (action.equals(MsgActionEnum.KEEPALIVE.type)) {
				//  2.4  心跳类型的消息
				System.out.println("收到来自channel为[" + currentChannel + "]的心跳包...");
			}else{
				System.out.println("收到来自channel为[" + currentChannel + "] ...");
			}

		}


	}
	
	/**
	 * 当客户端连接服务端之后（打开连接）
	 * 获取客户端的channle，并且放到ChannelGroup中去进行管理
	 */
	@Override
	public void handlerAdded(ChannelHandlerContext ctx) {
		users.add(ctx.channel());
	}

	@Override
	public void handlerRemoved(ChannelHandlerContext ctx) {
		
		String channelId = ctx.channel().id().asShortText();
		System.out.println("客户端被移除，channelId为：" + channelId);
		
		// 当触发handlerRemoved，ChannelGroup会自动移除对应客户端的channel
		users.remove(ctx.channel());
	}

	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
		cause.printStackTrace();
		// 发生异常之后关闭连接（关闭channel），随后从ChannelGroup中移除
		ctx.channel().close();
		users.remove(ctx.channel());
	}
}
